package com.crl.module.commands.history
{
	import com.crl.module.commands.events.CommandEvent;
	
	import flash.events.Event;
	import flash.events.EventDispatcher;
	
	public class HistoryManager extends EventDispatcher implements IHistoryCommand
	{
		/**
		 *	undo buffer.
		 */
		protected var undoBuffer:Vector.<IHistoryCommand>
		
		/**
		 *	redo buffer.
		 */
		protected var redoBuffer:Vector.<IHistoryCommand>
		
		public function HistoryManager() {
			undoBuffer=new Vector.<IHistoryCommand>();
			redoBuffer=new Vector.<IHistoryCommand>();
		}
		
		public function clear():void {
			undoBuffer.splice(0,undoBuffer.length);
			redoBuffer.splice(0,redoBuffer.length);
			
			this.dispatchEvent(new Event(Event.CHANGE));
		}
		
		public function get canUndo():Boolean {
			return undoBuffer.length >0;
		}
		
		public function get canRedo():Boolean {
			return redoBuffer.length > 0;
		}
		
		public function execute(e:*=null):void{
			if(e is IHistoryCommand == false){
				throw new Error("必须是个命令");
			}
			
			var command:IHistoryCommand=e as IHistoryCommand;
			redoBuffer.splice(0,redoBuffer.length);
			command.execute();
			undoBuffer.push(command);
			
			this.dispatchEvent(new Event(Event.CHANGE));
		}
		
		public function redo():void {
			if( canRedo==false ) {
				dispatchEvent(new CommandEvent(CommandEvent.EMPTY_REDO_BUFFER, null));
				return ;
			}
			
			var command:IHistoryCommand = IHistoryCommand(redoBuffer.pop());
			command.redo();
			undoBuffer.push(command);
			dispatchEvent(new CommandEvent(CommandEvent.REDO, command));
			
			this.dispatchEvent(new Event(Event.CHANGE));
		}
		
		public function undo():void {
			if( canUndo==false ) {
				dispatchEvent(new CommandEvent(CommandEvent.EMPTY_UNDO_BUFFER, null));
				return;
			} 
			
			var command:IHistoryCommand = IHistoryCommand(undoBuffer.pop());
			command.undo();
			redoBuffer.push(command);
			dispatchEvent(new CommandEvent(CommandEvent.UNDO, command));
			
			this.dispatchEvent(new Event(Event.CHANGE));
		}
		
		public function get name():String{
			return "manager";
		}
	}
	
}